#pragma once
#include<iostream>
#include<assert.h>
using namespace std;

namespace bit
{
	template<class T>
	class vector
	{
	public:
		typedef T* iterator;

		iterator begin()
		{
			return start;
		}

		iterator end()
		{
			return finish;
		}

		const iterator c_begin()const
		{
			return start;
		}

		const iterator c_end()const
		{
			return finish;
		}

		vector():
			start(nullptr),
			finish(nullptr),
			end_ofstorage(nullptr)
		{}

		vector(int n, const T& value = T()):vector()
		{
			
			resize(n,value);
		}

		template<class InputIterator>
		vector(InputIterator first, InputIterator last):vector()
		{
			assert(first < last);
			while (first != last)
			{
				push_back(*first);
				first++;
			}
		}

		vector(const vector<T>& v):vector(v.c_begin(),v.c_end())
		{
		}

		~vector()
		{
			delete[](start);
			start = nullptr;
			finish = nullptr;
			end_ofstorage = nullptr;
		}

		size_t size()const
		{
			return finish - start;
		}

		size_t capacity()const
		{
			return end_ofstorage - start;
		}

		void push_back(const T& value)
		{
			if (end_ofstorage == 0)
			{
				reserve(4);
			}
			if (finish == end_ofstorage)
			{
				reserve(capacity() * 2);
			}
			*finish = value;
			finish++;
		}

		void reserve(size_t capacity)
		{
			size_t oldsize = size();
			if (capacity > oldsize)
			{
				T* newstart = new T[capacity];
				for (size_t i = 0; i < size(); i++)
				{
					newstart[i] = start[i];
				}
				delete[](start);
				start = newstart;
				finish = start + oldsize;
				end_ofstorage = start + capacity;
			
			}
		}

		iterator insert(iterator pos,const T& value)
		{
			assert(pos >= start && pos <= finish);
			size_t relativePos = pos - start;
			if (finish == end_ofstorage)
			{
				reserve(capacity() * 2);
				pos = start + relativePos;
			}
			iterator end = finish;
			while (end >pos)
			{
				*(end) = *(end - 1);
				end--;
			}
			*pos = value;
			finish++;
			return pos;

		}


		void resize(size_t n, const T& value = T())
		{
			assert(n >= 0 && n != -1);
			if (n < size())
			{
				finish = start + n;
			}
			else
			{
				reserve(n);
				while (finish != start + capacity())
				{
					*finish = value;
					finish++;
				}
			}
		}

		vector<T>& swap(vector<T>& v)
		{
			std::swap(start, v.start);
			std::swap(finish, v.finish);
			std::swap(end_ofstorage, v.end_ofstorage);
			return *this;
		}

		void pop_back()
		{
			assert(size() > 0);
			finish--;
		}

		iterator erase(iterator pos)
		{
			assert(pos >= start && pos < finish);
			iterator ret = pos;
			while (pos < finish)
			{
				*pos = *(pos+1);
				pos++;
			}
			finish--;
			return ret;
		}

		const T& operator[](size_t index)const
		{
			assert(index < size() && index != -1);
			iterator ret = start + index;
			return *ret;
		}

		T& operator[](size_t index)
		{
			assert(index < size() && index != -1);
			iterator ret = start + index;
			return *ret;
		}

		vector<T>& operator=( vector<T> v)
		{

			return swap(v);
		}
	private:
		iterator start;
		iterator finish;
		iterator end_ofstorage;
	};

	

}